iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
4
Modern Web

重新認識 Flex 和 Grid系列 第 19

[Day19] grid-template 屬性之 rows/columns

  • 分享至 

  • xImage
  •  

雖然說網格線會隨著網格項目自動生成,但既然要使用網格系統,就要了解怎麼操控網格線,才能劃出各種多變的網格區域,然而畫網格線有很多種做法,且每種做法的語法也不同,怎麼利用 grid-template (網格樣板) 使用得當是一個難題。(本篇筆記較長約7000字,慎閱)

.container {
    grid-template: 
        none | 
        [<grid-template-rows> / <grid-template-columns>] |
        [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?;
}
預設:none

詳細使用方法種類見:
1.MDN
2.W3C


grid-template-rows/grid-template-columns

.container {
    grid-template-rows: none | <track-list> | <auto-track-list> ;
    grid-template-columns: 同上 ;
    grid-template: <grid-template-rows> / <grid-template-columns>
    grid: <grid-template-rows> / <grid-template-columns>
}
預設:none

英文小幫手:

grid-template 網格樣板
track-list 軌道列表

由於樣板中的軌道列表操縱方法非常多,雖然複雜但也增加了創造網格系統的彈性,想看有哪些的可以見The syntax of a track list,下面也會陸續介紹常用的網格線放置用法:

1.基本固定網格
2.minmax() 最小值與最大值
3.fr 份數
4.max-content/min-content 最小內容尺寸/最大內容尺寸
5.fit-content 貼合內容尺寸
6.repeat() 重複網格線及間距
7.auto-fill/autofit 自動重複網格線(自動填滿網格軌道)


放置網格線

網格內要放置幾條線?容器要分成幾等份?線和線之間的尺寸又是多少呢?我們將使用 grid-template-rows/grid-template-columns 放置網格線來解決以上的問題

首先要注意的是,定義網格線不等同於定義網格容器的大小,定義網格線是有機會不足或超出網格容器的;且在使用百分比時,計算尺寸會以網格容器的尺寸為目標來做計算,所以在樣板中寫 100% 就代表著那塊網格單元格要佔據網格容器的總寬/長。

1. 基本固定網格

a. 定義網格線間距

.container {
  grid-template-columns: 50px 50% 100px;
  grid-template-rows: 50px 100px 50px;
}

https://ithelp.ithome.com.tw/upload/images/20201004/20128346lGazvcQNqg.png

(淺藍色區域為網格容器,虛線內為網格格式環境)

b. 命名網格線:利用中括號自訂義,命名多個名稱則用空白做間隔([名稱 名稱 名稱 ....]),網格線間隔的數字即線段間距;行與列有自己的命名空間,所以可以取一樣的名字。

.container {
  grid-template-columns: 
      [start col-a] 50px [col-b] 50% [col-c] 100px [stop end last];
  grid-template-rows: 
      [start header] 50px [content] 100px [footer] 50px [stop end];
}

https://ithelp.ithome.com.tw/upload/images/20201004/201283467D4jTNFV3x.png

2. minmax() 比大小

另一個較為彈性的語法 minmax(),直接定義最小值和最大值,如果不小心把較大的數值寫在前面,就會取其後面為最小的值做為固定長度。

.container {
  grid-template-columns: 
      [start col-a] 50px [col-b] minmax(50px,100%) [col-c] 100px [stop end last];
  grid-template-rows: 
      [start header] 50px [content] 100px [footer] 50px [stop end];
}

如果網格項目的總內容尺寸超出網格容器,網格項目直接突破容器是正常的。

如果對於 minmax() 的值感到難以預判,可以利用 calc() 來做計算,假設要讓網格占滿螢幕高度,可以使用 calc(100% - 其他的尺寸)

然而只要 headerfooter 的數值需要變化,calc() 的數值就得做調整。另外,只要不是長度單位的都不能在 calc() 表達式中使用,這意味著它不能在()裡面放 fr ,因為 fr 不是長度單位,不過在 minmax() 是可以的。

3. fr 分配單位

如果想要讓網格單位變得有彈性,或許會想到可以使用 %,不過這邊有個新的比例分配單位 fr 可以做到更好的彈性。

frfraction,中文意思是分數,當使用在網格軌道上時,可以直接想像成 "我的這個空位要佔有總 fr 數量的幾等份"。

假設我的網格軌道要分成4等份:

.container {
    grid-template-columns: 1fr 1fr 1fr 1fr;
    /*等同於*/
    grid-template-columns: 25% 25% 25% 25%;
}

然而當我想任意修改等份時,使用 fr 只要知道 fr 要等份成幾塊即可,但使用 % 卻得再重新做計算。

.container {
    grid-template-columns: 2fr 3fr 1fr 1fr 3fr;
    /* 等同於 */
    grid-template-columns: 20% 25% 15% 15% 25%;
}

當然你還是可以和其他的單位混用。另外如果螢幕寬度縮小,沒有剩餘空間,就沒有足夠位置給 fr,就不會有 fr 這個位置。下面的例子如果網格寬度沒有超出700px,就不會有 1fr 這個空間出現;當網格寬度只有200px時,連 minmax(0,500px) 都不會出現(因為已經縮為0px)。

.container {
    grid-template-columns: 100px 1fr minmax(0, 500px) 100px
}

除此之外 fr 也可以使用小數點。

.container {
    grid-template-columns: 1fr 3.1415986fr 1fr
}

這種複雜的數學運算還是留給電腦吧。

4. max-content / min-content 依內容而變

如果需要不固定的網格內容(如共用模板),或是不確內容需要多少空間,這時可以使用 min-contentmax-content

  • max-content:給予網格區域所需的最大尺寸空間,內容盡可能避免折行。

  • min-content:給予網格區域所需的最小尺寸空間,內容盡可能的折行,但不會溢出邊界。

.container {
    grid-template-columns: max-content max-content max-content;
    grid-template-rows: max-content max-content max-content;
}

這樣的方式雖然所有的內容都會以不折行的方式,以最大尺寸來呈現在網格軌道中,這意味著如果內容尺寸超過網格容器,便會突破便網格容器。

常見混合使用

minmax() + fr

a. minmax() 和 fr 共用可以達到很好的 RWD 展現。

.container {
    grid-template-columns: minmax(100px, 200px) 1fr 1fr;
}

b. 把 fr 寫在 minmax() 裡面,想要設定最小寬度和彈性尺寸的佔位時可以使用這種方法。

.container {
    grid-template-rows: 3em minmax(5em, 1fr) 2em
}

minmax() + min-content/ max-content

a. minmax( 0, max-content )

最小為 0(當然也可以換其他數字來放最小值),網格區域如果沒有內容就會沒有尺寸;然而在這裡最大值使用 max-content ,當內容超出網格單元格時,內容會突破網格項目區域,而可能覆蓋在下一個網格項目之下。

.container {
    grid-template-colmns: 3em minmax(0, max-content) 2em
}

b. minmax( min-content, max-content )

縮到最小時會是內容可接受的最小尺寸,如果總內容超出容器還是會突破容器;拉到最大時會是內容最大尺寸,甚至會超出容器。

.container {
    grid-template-rows: 3em minmax(min-content, max-content) 2em
}

c. minmax( min-content, 數字 )

.container {
    grid-template-rows: 3em minmax(min-content, 500px) 2em
}

縮到最小時會是內容可接受的最小尺寸,如果總內容超出項目還是會突破容器;尺寸放大後最大就會是所設定的尺寸。

minmax() + min-content/ max-content + fr

如果用得恰到好處,可以展現 RWD,不會有內容的溢出問題,且網格項目最大只會到內容的寬度

.container {
    grid-template-columns: minmax(min-content, max-content) 1fr 1fr;
}

5. fit-content 貼合內容

文件:fit-content(argument) = min(max-content, max(min-content, argument))
引數 (argument) 可以是長度單位或是百分比

就表面上翻譯來說是「先比較內容最小尺寸和引數(argument)之間誰最大,再比較內容最大尺寸和上一個勝出的誰最大」,一定很難懂吧。

可以直接把 fit-content() 當作 minmax(min-content, max-content),當引數或超過引數尺寸的內容會作為內容尺寸的最大值 max-content,而網格區域又可以縮到內容的極限小 min-content,這樣比較好理解。

.container {
    grid-template-columns: fit-content(50px) 1fr 1fr;
}
/* 上面這個 fit-content 的最大寬度就是50px,最小寬度就是內容的極限小 */

6. repeat() 重複的網格線

如果遇到一再出現且相同尺寸的網格,可以利用 repeat() 來簡化程式碼。

.container{
  grid-template-columns: repeat(6, 1em 1fr);
}

前面第一個數代表重複次數,後面的代表要重複的間距,上面這個例子可以做到重複6次 1em 1fr的軌道模式。

repeat() 可以和其他尺寸軌道混合使用,甚至可以寫多個 repeat(),但不能使用巢狀寫法。(上面這個例子在最右邊加個 1em 可以讓畫面更平衡)

.container{
  grid-template-columns: repeat(6, 1em 1fr) 1em;
}

命名網格線也可以重複,甚至同時有兩個名稱,重複的名稱在某些情況下十分有用

.container{
  grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;
}

.container{
  grid-template-columns: repeat(3, [top] 5em [bottom]);
}
/* 等同於 */
.container{
  grid-template-columns: [top] 5em [bottom top] 5em [top bottom] 5em [bottom];
}

7. auto-fill / auto-fit 自動重複網格線(自動填滿軌道)

在使用 repeat() 時,如果不確定自己要的重複次數,可以使用 auto-fillautofit 讓重複的網格持續填滿。

  • auto-fill:自動填滿重複的軌道
.container{
  grid-template-columns: repeat(auto-fill, [top] 60px [bottom]);
}

https://ithelp.ithome.com.tw/upload/images/20201004/20128346BhwP0lNCYa.png

這樣網格容器就會每 60px 就多一條網格線,而剩下多出的會自占一格。

然而 auto-fill 有所限制,最多只能重複「兩條名稱線 + 中間一個固定尺寸單位」,頂多也只能少其中一條名稱線,只要不符合將無法重複。當然也不能同時宣告兩個或以上的 auto-fill

  • auto-fit:自動填滿重複的軌道,網格單元格內如果沒有彈性項目,那個網格單元格就會被折疊起來,尺寸變為0px。(後續會有可以指定彈性項目在網格的位置,則其他沒有放彈性項目的網格區域就會變為 0px)
.container{
  grid-template-columns: repeat(auto-fit, [top] 60px [bottom]);
}

https://ithelp.ithome.com.tw/upload/images/20201004/20128346Q3B4F0U8Ka.png


資料來源:


上一篇
[Day18] Grid 網格容器
下一篇
[Day20] grid-template 屬性之 areas
系列文
重新認識 Flex 和 Grid30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言